home *** CD-ROM | disk | FTP | other *** search
- /*
- nrand.c
- nrand(n), nrandU(), and nrandUL(n) all return a random integer in range [0, n-1],
- where n must be greater than zero. nrand() and nrandU() are faster, but nrandUL()
- has a much larger domain and range: unsigned long.
-
- nrand() is now obsolete, retained solely for backward compatibility. I suggest that
- all programs use nrandU() instead, which uses exactly the same code, but is now
- properly declared as accepting and returning an unsigned short.(Changing the type
- of nrand's returned value at this late date might have adversely affected existing
- programs.)
- HISTORY:
- 4/29/88 dgp wrote it.
- 3/19/90 dgp made it portable between THINK C and MPW C.
- 8/24/91 dgp removed unnecessary (long) in preprocessor statement, since keywords
- are undefined at preprocessor time in ANSI C.
- 10/21/91 dgp Removed obsolete inclusion of MacProto.h.
- 9/13/92 dgp Changed nrand's argument type from int to short, since the algorithm assumes
- that the argument is a short.
- Using THINK C's Disassembler I noticed that I could substantially speed
- up the code, replacing the long division by a bit shift. The answers for
- legal values of n, i.e. n>0, are unchanged, but the answers for values of
- n outside that range have changed because I now explicitly cast n
- to unsigned long rather than long. (Bit shifting and division give different
- answers when the numerator is negative.)
- Added nrandU() and nrandUL().
- 9/18/92 dgp Cast nrand() from int to unsigned short to prompt THINK C to generate
- tighter code.
- */
- #include "VideoToolbox.h"
- #include <assert.h>
-
- #if RAND_MAX > LONG_MAX/SHRT_MAX
- #error "nrand() assumes that a long can hold the product of short & rand()."
- #endif
-
- int nrand(short n)
- {
- #if RAND_MAX+1L==0x8000
- return (unsigned long)n*rand()>>15;
- #else
- return (unsigned long)n*rand()/(RAND_MAX+1L);
- #endif
- }
- /*
- nrand:
- 00000000 LINK A6,#$0000
- 00000004 JSR $0000(A5)
- 00000008 MULS.W $0008(A6),D0
- 0000000C MOVEQ #$0F,D1
- 0000000E LSR.L D1,D0
- 00000010 UNLK A6
- 00000012 RTS
- */
-
- #if RAND_MAX > ULONG_MAX/USHRT_MAX
- #error "nrandU() assumes that an unsigned long can hold the product of unsigned short & rand()."
- #endif
-
- unsigned short nrandU(unsigned short n)
- {
- #if RAND_MAX+1L==0x8000
- return (unsigned long)n*(unsigned short)rand()>>15;
- #else
- return (unsigned long)n*(unsigned short)rand()/(RAND_MAX+1L);
- #endif
- }
- /*
- nrandU:
- 00000000 LINK A6,#$0000
- 00000004 JSR $0000(A5)
- 00000008 MULU.W $0008(A6),D0
- 0000000C MOVEQ #$0F,D1
- 0000000E LSR.L D1,D0
- 00000010 UNLK A6
- 00000012 RTS
- */
-
- unsigned long nrandUL(unsigned long n)
- {
- return (unsigned long)((double)n*randUL()/(ULONG_MAX+1.0));
- }
-